<?php
/**
 * User: hnh0000
 * Time: 2020/5/27 9:46 下午
 * Email: hnh@hnh117.com
 * Blog: blog@hnh117.com
 */
namespace addons\git\library;

use app\common\library\Log;
use think\Exception;

class Git {

    public static function getPath()
    {
        return ROOT_PATH;
    }

    /**
     * 执行
     * @return mixed
     */
    public static function exec()
    {
        self::isHaveGit();
        $path = self::getPath();
        $type = self::source();

        $config = get_addon_config('git');

        // 判断是否可以更新
        try{
            $pullInfo = self::pullInfo();
        }catch (\Exception $e) {
            return [
                'type' => $type,
                'status' => 3,
                'msg' => $e->getMessage()
            ];
        }

        $exec = $config['pull'];
        $exec = str_replace('{$path}', $path, $exec);


        exec($exec, $res);
//        exec("cd /home/www/CI/ ; git pull", $res);

//        throw new \Exception($exec.'<-=->'.implode($res));

        try{

            if (!count($res)) {

                //$who = system("whoami");

                throw new \Exception('请确保.git文件权限拥有权限-'.$exec);
            }

            if (mb_stripos($res[0], 'Already') !== false) {
                return [
                    'status' => 3,
                    'msg' => '已是最新版本',
                    'type' => $type
                ];
            }

            $exec = $config['pull_after'];
            if ($exec) {
                $exec = str_replace('{$path}', $path, $exec);
                exec($exec);
            }

            return [
                'status' => 1,
                'msg' => $pullInfo['message'],
                'type' => $type
            ];
        }catch (\Exception $e) {
            return [
                'status' => 0,
                'msg' => $e->getMessage(),
                'type' => $type
            ];
        }
    }


    /**
     * 获取拉取信息
     */
    public static function pullInfo()
    {
        $password = self::password();
        $res = [
            'message' => null, // 提交备注
            'password' => null // 密码
        ];

        $type = self::source();
        $res = self::$type();

        $platform = get_addon_config('git')['platform'];
        $platform = explode(',', $platform);

        if (!in_array($type, $platform)) {
            throw new \Exception('未开通'.$type);
        }

        if ($res['password'] != $password && $res['password'] !== true) {
            throw new \Exception('密码错误');
        }

        return $res;
    }


    public static function password()
    {
        return get_addon_config('git')['password'];
    }

    /**
     * gitee平台
     */
    public static function gitee()
    {
        $param = input();
        if ($param['hook_name'] != 'push_hooks') {
            throw new \Exception('仅支持 push 事件');
        }
        $res = [
            'message' => $param['commits'][0]['message'],
            'password' => $param['password']
        ];
        return $res;
    }

    public static function github()
    {
        if (request()->header('x-github-event') != 'push') {
            throw new \Exception('仅支持 push 事件');
        }

        $parma = json_decode(input('payload'), true);
        $secret = self::password();
        $json = file_get_contents('php://input');
        $content = json_decode($json, true);
        $signature = $_SERVER['HTTP_X_HUB_SIGNATURE'];
        list($algo, $hash) = explode('=', $signature, 2);

        $payloadHash = hash_hmac($algo, $json, $secret);

        $password = $hash === $payloadHash;

        $res = [
            'message' => $parma['commits'][0]['message'],
            'password' => $password
        ];

        return $res;
    }


    public static function coding()
    {
        $param = input();

        if (request()->header('x-coding-event') != 'push') {
            throw new \Exception('仅支持 push 事件');
        }

        $password = self::password();
        $json = file_get_contents('php://input');
        $content = json_decode($json, true);
        $signature = request()->header('X-Coding-Signature');
        list($algo, $hash) = explode('=', $signature, 2);
        $payloadHash = hash_hmac($algo, $json, $password);

        $password = $hash === $payloadHash;

        $res = [
            'message' => $param['commits'][0]['message'],
            'password' => $password
        ];
        return $res;
    }


    /**
     * 未知
     */
    public static function unknow()
    {
        throw new \Exception('未知平台');
    }

    /**
     * 获取请求来源
     * @return string
     */
    public static function source()
    {
        $gitee = request()->header('x-gitee-event');
        if ($gitee) {
            return 'gitee';
        }
        $github = request()->header('x-gitHub-event');
        if ($github) {
            return 'github';
        }
        $coding = request()->header('x-coding-event');
        if ($coding) {
            return 'coding';
        }
        return 'unknow';
    }


    /**
     * 是为使用git版本控制
     */
    public static function isHaveGit()
    {
        self::nowCommitId();
        return true;
    }


    /**
     * 获取当前版本信息
     */
    public static function nowInfo()
    {
        $commitId = self::nowCommitId();
        $path = self::getPath();
        $exec = "cd {$path} &&  git show {$commitId}";
        exec($exec, $res);
        return $res;
    }

    /**
     * 获取当前 commitId
     */
    public static function nowCommitId()
    {
        $path = self::getPath();
        $exec = "cd {$path} &&  git rev-parse HEAD";

        try{
            exec($exec, $res);
            $commitId = $res[0];
            if (mb_strlen($commitId) == 40) {
                return $commitId;
            }
            throw new \Exception($commitId);
        }catch (\Exception $e) {
            throw new \Exception('获取失败，请检查是否使用git');
        }

    }
}